package com.pingan.common.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Component;

/**
 * @author xxu
 * @date 2011-3-28
 * @version $id$ <br>
 *          waitFor() 导致当前线程等待，如有必要，一直要等到由该 Process 对象表示的进程已经终止。
 *          但是如果我们在调用此方法时，如果不注意的话，很容易出现主线程阻塞，Process也挂起的情况。在调用waitFor()
 *          的时候，Process需要向主线程汇报运行状况，所以要注意清空缓存区，即InputStream和ErrorStream
 *          另外：永远要在调用waitFor()方法之前读取数据流<br>
 *          永远要先从标准错误流中读取，然后再读取标准输出流<br>
 *          Process.getInputStream 可以读取新开启的程序的标准输出的内容<br>
 *          Process.getOutputStream 输出一些内容，新开启的程序的 System.in可以读得到<br>
 *          exitValue()返回1表示，有1个子进程无法终止，返回2，表示有2个子进程无法终止，
 */
@Component
public class ShellExecutor {

	private static final Log log = LogFactory.getLog(ShellExecutor.class);

	public void excecute(String shell, String[] args) {
		StringBuilder sb = new StringBuilder();
		String cmd[] = new String[1 + args.length];
		cmd[0] = shell;

		for (int i = 0; i < args.length; i++) {
			cmd[1 + i] = args[i];
		}

		for (String s : cmd) {
			sb.append(s).append(" ");
		}

		try {

			log.info("     -->  " + sb.toString());
			Process process = null;

			Runtime rt = Runtime.getRuntime();
			// process = rt.exec(sb.toString());
			process = rt.exec(cmd);
			InputStream errorStream = process.getErrorStream();
			BufferedReader br = new BufferedReader(new InputStreamReader(
					errorStream));
			StringBuilder buf = new StringBuilder(); // 保存输出结果流
			try {
				String line = null;
				while ((line = br.readLine()) != null) {
					buf.append(line); // 循环等待ffmpeg进程结束
				}
				log.info("          " + buf.toString());
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				if (br != null) {
					try {
						br.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}

			final InputStream inputStream = process.getInputStream();
			BufferedReader br2 = new BufferedReader(new InputStreamReader(
					inputStream));
			try {
				String lineC = null;
				while ((lineC = br2.readLine()) != null) {
					if (lineC != null) {
						System.out.println(lineC);
						log.info("          " + lineC);
					}

				}
			} catch (IOException e) {
				e.printStackTrace();
			} finally {
				if (br2 != null) {
					try {
						br2.close();
					} catch (IOException e) {
						e.printStackTrace();
					}
				}
			}

			log.info("          shell executing ......");
			process.waitFor();
			log.info("          shell end ");
			inputStream.close();
			errorStream.close();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {

		}
	}
}
